from odoo import fields, models, _, api
from odoo.exceptions import ValidationError, UserError


class SaleChangeApply(models.Model):
    _name = 'sb.plan.change.apply'
    _inherit = ['portal.mixin', 'mail.thread.main.attachment', 'mail.activity.mixin']

    name = fields.Char(String="Name", default="New")
    state = fields.Selection([
        ('draft', 'Draft'),
        ('wait_approval', 'Waiting for Approval'),
        ('approved', 'Approved'),
        ('rejected', 'Rejected')
    ], tracking=True, default='draft', copy=False)

    apply_type = fields.Selection([
        ('planned_receiving_date', 'Planned Receiving Date')
    ], string="Apply Type")

    sale_order_id = fields.Many2one('sale.order', string='Sale Order', domain=[('state', '=', 'sale')], required=True)
    planned_receiving_date = fields.Datetime(string='Planned Receiving Date',
                                             related='sale_order_id.planned_receiving_date', store=True)
    user_id = fields.Many2one('res.users', string="Salesperson", related='sale_order_id.user_id')

    new_planned_receiving_date = fields.Datetime(string='New Planned Receiving Date', required=True)
    # 当前审批工作流
    sb_workflow_id = fields.Many2one('sb.workflow', string="Current Approval Workflow", copy=False)
    sb_workflow_state = fields.Selection(related="sb_workflow_id.state", readonly=True, string="Approval Status",
                                         store=True)
    sb_workflow_item_ids = fields.One2many(related="sb_workflow_id.sb_workflow_item_ids", string="Approval Items",
                                           copy=False)

    def create_workflow(self):
        self.ensure_one()
        self.state = 'wait_approval'
        self.name = self.env['ir.sequence'].next_by_code('sb.sale.change.apply')

        # 创建审批流
        new_wf_id = self.env['sb.workflow'].sudo().create({
            'name': self.name + '- Approval Flow',
            'approval_time': fields.Datetime.now(),
            'workflow_type': 'plan_change_apply',
            'sb_plan_change_apply_id': self.id
        })
        self.sb_workflow_id = new_wf_id.id

        # id = 190，需替换指定审批用户的id。
        # 当订单的跟单员为空时，使用默认审批用户
        default_approval_user_id = 190
        approval_user = self.user_id if self.user_id else self.env['res.users'].browse(default_approval_user_id)
        if not approval_user:
            raise ValidationError(_('Default approval user not found.'))

        self.env['sb.workflow.item'].sudo().create({
            'name': '跟单员审批',
            'user_group_ids': [approval_user.id],
            'sb_workflow_id': new_wf_id.id,
            'state': 'approval',
            'audit_level': 1
        })

    @api.constrains('sb_workflow_state')
    def _constrains_sb_workflow_state(self):
        for record in self.sudo():
            if record.state in ['draft']:
                continue

            if record.sb_workflow_state == 'approve':
                record.state = 'approved'
                # 审批通过，更新订单的计划日期。原计划日期始终保持第一次的计划日期。
                origin_date = record.planned_receiving_date if not record.sale_order_id.origin_planned_receiving_date else record.sale_order_id.origin_planned_receiving_date
                record.sale_order_id.sudo().write({
                    'planned_receiving_date': record.new_planned_receiving_date,
                    'origin_planned_receiving_date': origin_date
                })
            elif record.sb_workflow_state == 'fail_to_approve':
                record.state = 'rejected'

    @api.constrains('new_planned_receiving_date')
    def _constrains_new_planned_receiving_date(self):
        for record in self:
            if record.new_planned_receiving_date == record.planned_receiving_date:
                raise ValidationError(
                    _('New Planned Receiving Date should not be the same as the current Planned Receiving Date.'))

    def unlink(self):
        if self.filtered(lambda x: x.state != 'draft'):
            raise UserError(_('Deletion error, only the draft state is allowed to be deleted!'))

        return super().unlink()
